package com.example.javapracticaltraining.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.javapracticaltraining.entity.R;
import com.example.javapracticaltraining.entity.pojo.StaffSchedule;
import com.example.javapracticaltraining.entity.pojo.MedicalStaff;
import com.example.javapracticaltraining.service.StaffScheduleService;
import com.example.javapracticaltraining.service.MedicalStaffService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.util.List;

/**
 * 医护人员排班管理控制器
 */
@RestController
@RequestMapping("/staffschedules")
@Tag(name = "排班管理", description = "医护人员排班的增删改查操作")
public class StaffScheduleController {

    @Autowired
    private StaffScheduleService staffScheduleService;

    @Autowired
    private MedicalStaffService medicalStaffService;

    /**
     * 获取所有排班
     * @return 排班列表
     */
    @Operation(summary = "获取所有排班", description = "返回系统中所有医护人员的排班列表")
    @ApiResponse(responseCode = "200", description = "成功获取排班列表")
    @GetMapping
    public R<List<StaffSchedule>> getAllSchedules() {
        List<StaffSchedule> schedules = staffScheduleService.list();
        return R.success(schedules);
    }

    /**
     * 分页获取排班
     * @param page 页码
     * @param pageSize 每页大小
     * @param staffId 医护人员ID（可选，用于筛选）
     * @param startDate 开始日期（可选，用于筛选）
     * @param endDate 结束日期（可选，用于筛选）
     * @return 分页后的排班列表
     */
    @Operation(summary = "分页获取排班", description = "根据条件分页查询排班，支持按医护人员ID和日期范围筛选")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "成功获取分页排班列表")
    })
    @GetMapping("/page")
    public R<Page<StaffSchedule>> getSchedulesByPage(
            @Parameter(description = "页码，默认为1") @RequestParam(defaultValue = "1") int page,
            @Parameter(description = "每页记录数，默认为10") @RequestParam(defaultValue = "10") int pageSize,
            @Parameter(description = "医护人员ID，可选参数") Integer staffId,
            @Parameter(description = "开始日期，可选参数，格式：yyyy-MM-dd") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @Parameter(description = "结束日期，可选参数，格式：yyyy-MM-dd") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {

        Page<StaffSchedule> pageInfo = new Page<>(page, pageSize);
        LambdaQueryWrapper<StaffSchedule> queryWrapper = new LambdaQueryWrapper<>();

        if (staffId != null) {
            queryWrapper.eq(StaffSchedule::getStaffId, staffId);
        }

        if (startDate != null) {
            queryWrapper.ge(StaffSchedule::getScheduleDate, startDate);
        }

        if (endDate != null) {
            queryWrapper.le(StaffSchedule::getScheduleDate, endDate);
        }

        // 默认按日期和开始时间排序
        queryWrapper.orderByAsc(StaffSchedule::getScheduleDate)
                   .orderByAsc(StaffSchedule::getStartTime);

        staffScheduleService.page(pageInfo, queryWrapper);
        return R.success(pageInfo);
    }

    /**
     * 根据ID获取排班
     * @param scheduleId 排班ID
     * @return 排班信息
     */
    @Operation(summary = "根据ID获取排班", description = "根据排班ID获取排班详细信息")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "成功获取排班信息"),
        @ApiResponse(responseCode = "404", description = "未找到该排班记录")
    })
    @GetMapping("/{scheduleId}")
    public R<StaffSchedule> getSchedule(@Parameter(description = "排班ID") @PathVariable Integer scheduleId) {
        StaffSchedule schedule = staffScheduleService.getById(scheduleId);
        if (schedule != null) {
            return R.success(schedule);
        }
        return R.failure(404, "未找到该排班记录");
    }

    /**
     * 获取指定医护人员的排班
     * @param staffId 医护人员ID
     * @return 排班列表
     */
    @Operation(summary = "获取指定医护人员的排班", description = "根据医护人员ID获取其所有排班记录")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "成功获取医护人员的排班列表"),
        @ApiResponse(responseCode = "404", description = "未找到该医护人员")
    })
    @GetMapping("/staff/{staffId}")
    public R<List<StaffSchedule>> getSchedulesByStaff(@Parameter(description = "医护人员ID") @PathVariable Integer staffId) {
        // 检查医护人员是否存在
        MedicalStaff staff = medicalStaffService.getById(staffId);
        if (staff == null) {
            return R.failure(404, "未找到该医护人员");
        }

        LambdaQueryWrapper<StaffSchedule> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StaffSchedule::getStaffId, staffId)
                   .orderByAsc(StaffSchedule::getScheduleDate)
                   .orderByAsc(StaffSchedule::getStartTime);

        List<StaffSchedule> schedules = staffScheduleService.list(queryWrapper);
        return R.success(schedules);
    }

    /**
     * 获取指定日期的排班
     * @param date 日期
     * @return 排班列表
     */
    @Operation(summary = "获取指定日期的排班", description = "根据日期获取所有医护人员在该日的排班记录")
    @ApiResponse(responseCode = "200", description = "成功获取指定日期的排班列表")
    @GetMapping("/date/{date}")
    public R<List<StaffSchedule>> getSchedulesByDate(
            @Parameter(description = "日期，格式：yyyy-MM-dd") @PathVariable @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) {

        LambdaQueryWrapper<StaffSchedule> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StaffSchedule::getScheduleDate, date)
                   .orderByAsc(StaffSchedule::getStartTime);

        List<StaffSchedule> schedules = staffScheduleService.list(queryWrapper);
        return R.success(schedules);
    }

    /**
     * 添加新的排班
     * @param schedule 排班信息
     * @return 操作结果
     */
    @Operation(summary = "添加排班", description = "创建新的医护人员排班记录")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "排班添加成功"),
        @ApiResponse(responseCode = "404", description = "未找到相关医护人员"),
        @ApiResponse(responseCode = "400", description = "该医护人员在所选时间段内已有排班")
    })
    @PostMapping
    public R<String> addSchedule(@RequestBody StaffSchedule schedule) {
        // 检查医护人员是否存在
        MedicalStaff staff = medicalStaffService.getById(schedule.getStaffId());
        if (staff == null) {
            return R.failure(404, "未找到该医护人员");
        }

        // 设置默认值
        if (schedule.getStatus() == null) {
            schedule.setStatus(1); // 默认正常状态
        }

        // 检查是否有时间冲突
        LambdaQueryWrapper<StaffSchedule> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StaffSchedule::getStaffId, schedule.getStaffId())
                   .eq(StaffSchedule::getScheduleDate, schedule.getScheduleDate())
                   .and(i -> i.lt(StaffSchedule::getEndTime, schedule.getStartTime())
                             .or()
                             .gt(StaffSchedule::getStartTime, schedule.getEndTime()));

        List<StaffSchedule> conflictSchedules = staffScheduleService.list(queryWrapper);
        if (!conflictSchedules.isEmpty()) {
            return R.failure(400, "该医护人员在所选时间段内已有排班");
        }

        staffScheduleService.save(schedule);
        return R.success("排班添加成功");
    }

    /**
     * 更新排班信息
     * @param schedule 排班信息
     * @return 操作结果
     */
    @Operation(summary = "更新排班", description = "根据ID更新医护人员排班信息")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "排班信息更新成功"),
        @ApiResponse(responseCode = "400", description = "排班ID不能为空或该医护人员在所选时间段内已有排班"),
        @ApiResponse(responseCode = "404", description = "未找到相关排班记录或医护人员")
    })
    @PutMapping
    public R<String> updateSchedule(@RequestBody StaffSchedule schedule) {
        // 检查是否存在
        if (schedule.getScheduleId() == null) {
            return R.failure(400, "排班ID不能为空");
        }

        StaffSchedule existingSchedule = staffScheduleService.getById(schedule.getScheduleId());
        if (existingSchedule == null) {
            return R.failure(404, "未找到该排班记录");
        }

        // 检查医护人员是否存在
        MedicalStaff staff = medicalStaffService.getById(schedule.getStaffId());
        if (staff == null) {
            return R.failure(404, "未找到该医护人员");
        }

        // 检查是否有时间冲突（排除自身）
        LambdaQueryWrapper<StaffSchedule> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StaffSchedule::getStaffId, schedule.getStaffId())
                   .eq(StaffSchedule::getScheduleDate, schedule.getScheduleDate())
                   .ne(StaffSchedule::getScheduleId, schedule.getScheduleId())
                   .and(i -> i.lt(StaffSchedule::getEndTime, schedule.getStartTime())
                             .or()
                             .gt(StaffSchedule::getStartTime, schedule.getEndTime()));

        List<StaffSchedule> conflictSchedules = staffScheduleService.list(queryWrapper);
        if (!conflictSchedules.isEmpty()) {
            return R.failure(400, "该医护人员在所选时间段内已有排班");
        }

        staffScheduleService.updateById(schedule);
        return R.success("排班信息更新成功");
    }

    /**
     * 取消排班
     * @param scheduleId 排班ID
     * @return 操作结果
     */
    @Operation(summary = "取消排班", description = "将排班状态设置为已取消")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "排班已取消"),
        @ApiResponse(responseCode = "404", description = "未找到该排班记录")
    })
    @PutMapping("/{scheduleId}/cancel")
    public R<String> cancelSchedule(@Parameter(description = "排班ID") @PathVariable Integer scheduleId) {
        StaffSchedule schedule = staffScheduleService.getById(scheduleId);
        if (schedule == null) {
            return R.failure(404, "未找到该排班记录");
        }

        schedule.setStatus(0); // 设置为已取消
        staffScheduleService.updateById(schedule);
        return R.success("排班已取消");
    }

    /**
     * 删除排班
     * @param scheduleId 排班ID
     * @return 操作结果
     */
    @Operation(summary = "删除排班", description = "根据ID删除医护人员排班")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "排班删除成功"),
        @ApiResponse(responseCode = "404", description = "未找到该排班记录")
    })
    @DeleteMapping("/{scheduleId}")
    public R<String> deleteSchedule(@Parameter(description = "排班ID") @PathVariable Integer scheduleId) {
        // 检查是否存在
        StaffSchedule existingSchedule = staffScheduleService.getById(scheduleId);
        if (existingSchedule == null) {
            return R.failure(404, "未找到该排班记录");
        }

        // 执行删除操作
        staffScheduleService.removeById(scheduleId);
        return R.success("排班删除成功");
    }
}
